﻿using Inovout.Gis.Geometry;
using System.Reflection;
using System.Collections.Generic;
using System.Linq;

namespace Inovout.Gis
{
    public abstract class GeometryObject : IGeometryObject, IGeometryInfo
    {
        #region Constructor

        protected IGeometryInfo geometryInfo;

        protected GeometryObject(IGeometryInfo geometryInfo)
        {
            this.geometryInfo = geometryInfo;
        }

        #endregion

        #region Layer

        private IGeometryLayerObject layer;
        public IGeometryLayerObject Layer
        {
            get
            {
                if (layer == null)
                {
                    layer = geometryInfo.Layer as IGeometryLayerObject;
                }

                return layer;
            }
            internal set { layer = value; }
        }


        IGeometryLayerInfo IGeometryInfo.Layer
        {
            get { return geometryInfo.Layer; }
        }

        #endregion

        #region GeometryInfoInterface
        public IGeometryInfo GetIntersectGeometry(IGeometryObject geometry)
        {
            return GetIntersectGeometry(geometry as IGeometryInfo);
        }
        public IGeometryInfo GetIntersectGeometry(IGeometryInfo geometry)
        {
            return geometryInfo.GetIntersectGeometry(geometry);
        }

        public double Area
        {
            get { return geometryInfo.Area; }
        }

        public object Shape
        {
            get { return geometryInfo.Shape; }
        }


        public IGisRow Row
        {
            get { return geometryInfo.Row; }
        }
        public object GeometryId
        {
            get { return geometryInfo.GeometryId; }
        }

        #endregion

        #region NetArea
 

        public double NetArea
        {
            get
            {
                return CalculateNetArea();
            }
        }
        protected virtual double CalculateNetAreaFromSpace()
        {
            double netarea = geometryInfo.Area;
            foreach (var geometry in GetIntersectedGeometries())
            {
                netarea -= geometry.Area;
            }
            return netarea;
        }
        private List<IGeometryInfo> GetIntersectedGeometries()
        {
            IGeometryLayerObject[] intersectedLayers = GetIntersectedLayers();
            if (intersectedLayers == null || intersectedLayers.Length == 0)
            {
                return geometryInfo.GetIntersectedGeometries(GetIntersectedLayerNames());
            }
            else
            {
                return geometryInfo.GetIntersectedGeometries(intersectedLayers.Cast<IGeometryLayerInfo>().ToArray());
            }

        }
        protected virtual IGeometryLayerObject[] GetIntersectedLayers()
        {
            return new IGeometryLayerObject[0];
        }

        protected virtual string[] GetIntersectedLayerNames()
        {
            return new string[0];
        }

        protected readonly string NetAreaProperyName = "Area";
        protected virtual double CalculateNetAreaFromRepository()
        {
            PropertyInfo areaproperyInfo = Domain.GetType().GetProperty(NetAreaProperyName);
            if (areaproperyInfo == null)
            {
                return 0;
            }
            else
            {
                return double.Parse(areaproperyInfo.GetValue(Domain, null).ToString());
            }
        }
        private double CalculateNetArea()
        {
            //衔从业务表中获取
            double netArea = 0;
            if (Domain != null)
            {
                netArea = CalculateNetAreaFromRepository();
            }
            if (netArea == 0)
            {
                //再做空间计算
                netArea = CalculateNetAreaFromSpace();
            }
            return netArea;
        }

        #endregion

        #region Domain

        public object Domain
        {
            get
            {
                if (domain == null)
                {
                    BuildDomain();
                }
                return domain;
            }
            protected set { domain = value; }
        }

        private object domain;
        protected virtual void BuildDomain()
        {

        }

        public void StoreNetArea()
        {
            if (geometryInfo.RelationId == null)
            {
                Row[NetAreaProperyName]= CalculateNetAreaFromSpace();
                Row.Store();
            }
            else
            {
            }
        }
        #endregion


        public object RelationId
        {
            get { return geometryInfo.RelationId; }
        }

        public List<IGeometryInfo> GetIntersectedGeometries(params string[] layerNames)
        {
            return geometryInfo.GetIntersectedGeometries(layerNames);
        }

        public List<IGeometryInfo> GetIntersectedGeometries(params IGeometryLayerInfo[] layers)
        {
            return geometryInfo.GetIntersectedGeometries(layers);
        }

        //public double EnvelopeMinX
        //{
        //    get { return geometryInfo.EnvelopeMinX; }
        //}
        //public double EnvelopeMaxX
        //{
        //    get { return geometryInfo.EnvelopeMaxX; }
        //}
        //public double EnvelopeMinY
        //{
        //    get { return geometryInfo.EnvelopeMinY; }

        //}
        //public double EnvelopeMaxY
        //{
        //    get { return geometryInfo.EnvelopeMaxY; }

        //}
    }
}
